<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Angular MVVM模式的简单实现_封装指令</title>
</head>
<body onload="init()">
<h3>mvvm simple model</h3>
<div ng-scope>
  <p>绑定测试： <span ng-bind="test"></span></p>
  <p>依赖数据测试： <span ng-bind="dependence"></span></p>
  <input type="text" ng-model="test" value=""/>
  <button ng-click="resetdata()">重置数据</button>
</div>
<br>
<hr>
<h3>不同的scope</h3>
<div ng-scope>
  <p>绑定测试： <span ng-bind="test"></span></p>
  <p>依赖数据测试： <span ng-bind="dependence"></span></p>
  <input type="text" ng-model="test" value=""/>
  <button ng-click="resetdata()">重置数据</button>
</div>

<script>

function Scope(node, declareData, computeData) {
  this.$scope = {};
  this.dom = node || document.body;
  this.bindDom = null;

  var self = this;

  this.declareData = function () {
    declareData.call(self);
  };

  this.computeData = function () {
    computeData.call(self);
  }

  this.init();
}

Scope.prototype.apply = function () {
  var self = this;
  // 计算依赖数据
  this.computeData();
  // 更新视图
  this.bindDom.forEach(function (item) {
    item.innerText = self.$scope[item.getAttribute('ng-bind')];
  });
}

Scope.prototype.init = function () {
  var self = this;
  // watch过程，未做脏检查
  var modelDom = self.dom.querySelectorAll('[ng-model]');
  modelDom.forEach(function (el) {
    // ng接管各种用户输入事件来更新绑定数据，然后计算整个模型数据，最后再调用apply去更新视图
    el.addEventListener('keyup', function () {
      self.$scope[el.getAttribute('ng-model')] = el.value;
      self.apply();
    });
    // el.addEventListener('keydown', function (e) {});
    // el.addEventListener('change', function (e) {}); ……
  });

  // 绑定用户事件
  var clickDom = self.dom.querySelectorAll('[ng-click]');
  clickDom.forEach(function (el) {
    el.addEventListener('click', function (event) {
      self.$scope[el.getAttribute('ng-click').replace('()', '')]();
      self.apply();
    })
  });

  // 指定绑定数据的元素
  self.bindDom = self.dom.querySelectorAll('[ng-bind]');

  // 初始化数据
  self.declareData();

  // 应用数据并更新视图
  self.apply();
}

function init() {
  var scopes = document.querySelectorAll('[ng-scope]');
  new Scope(scopes[0], function () {
    var self = this;
    self.$scope.test = 'test';
    self.$scope.resetdata = function () {
      self.$scope.test = 'reset';
    };
  }, function () {
    var self = this;
    self.$scope.dependence = 'dependence: ' + self.$scope.test;
  });

  new Scope(scopes[1], function () {
    var self = this;
    self.$scope.test = '测试';
    self.$scope.resetdata = function () {
      self.$scope.test = '重置';
    };
  }, function () {
    var self = this;
    self.$scope.dependence = '依赖: ' + self.$scope.test;
  });

  //        new Scope(scopes[0]);

}

</script>
</body>
</html>